
using ReactiveUI.Fody.Helpers;
using Shinva.LADModel.Abstractions;
using Shinva.LADModel.Helper;
using Shinva.LADModel.Models;
using Shinva.LADModel.Type.BitLogicOperations;
using Shinva.LADModel.Utilities;
using Shinva.PLCModel.Helper;
using Shinva.PLCModel.Models;
using Shinva.PLCModel.Service;
using Shinva.Variables.Models;
using Shinva.Variables.Type.bit;
using Shinva.Variables.Type.combination;
using Shinva.Variables.Type.time;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;

namespace Shell.ViewModels
{
    public class MainWindowViewModel : ReactiveUI.ReactiveObject
    {
        [Reactive]
        public string Title { get; set; } = "Shinva PLC Editor";

        private PlcModelService plcModelService { get; set; } = new PlcModelService();

        /// <summary>
        /// 变量表的视图模型，与业务模型进行绑定
        /// </summary>
        public ObservableCollection<PlcVariableViewModel> Variables { get; }
            = new ObservableCollection<PlcVariableViewModel>();
        public Diagram fil { get; set; } = new Diagram();
        /// <summary>
        /// 梯形图遍历的路径
        /// </summary>
        [Reactive]
        public List<string> PathArray { get; set; }
        public MainWindowViewModel()
        {
            
            // 初始化一个FB块
            var fb = new PlcFB(Shinva.PLCModel.ProgrammingLanguage.LAD, 1, "polygon");
            fb.InputStruct.AddMember(new PlcBool() { Name = "startButton",Value = false});
            //fb.InputStruct.AddMember((new PlcDWord("Counter", 0x12345678)));
            //fb.InputStruct.AddMember(new PlcDate("ProductionDate", new DateTime(2023, 10, 1)));
            //fb.StaticStruct.AddMember(new PlcBool("StaticButton", true));
            //fb.StaticStruct.AddMember(new PlcBool("StaticButton", true));



            testData();

            plcModelService.FBList.Add(fb);
            


            InitMyTree(fb.LADTree);

            //编译一下偏移地址
            fb.InterfaceVariableTable.compileAddr();
            //变量表放置到界面的数据模型中
            LoadData(fb.InterfaceVariableTable);
            //梯形图遍历的路径放置到数据模型中
            PathArray =  DiagramTraversal.GetPathArray(fil);
        }
        private void LoadData(NormalVariableTable table)
        {
            var test = table.GetMembers();
            foreach (var member in table.GetMembers())
            {
                Variables.Add(new PlcVariableViewModel(member));
            }
        }

       
        public void InitMyTree(Diagram _nodeTree)
        {
            var net1 = new Powerrail();
            _nodeTree.Networks.Add(net1);


               //new DataPointer();

            var X0 = new Contact() { Name = "X0" };
            var X1 = new Contact() { Name = "X1" };
            var Y0 = new Contact() { Name = "Y0" };
            var Y0C = new Coil() { Name = "Y0" };
            var Y1  = new Coil() { Name = "Y1" };
            var Y2  = new Coil() { Name = "Y2" };
            var Y3  = new Coil() { Name = "Y3" };
            var vn = new VirtualNode();
            var powerrail = new Powerrail();
            //这是母线连接，就不传入参数了


            //图元之间连接，需要参数
            // List<(INode node, string name)> list = new List<(INode node, string name)>();
            //list.Add((powerrail, "Powerrail"));
            //list.Add((X0, "in"));
            //list.Add((Y0, "in"));

            //测试1
            //WireConnector.Connect(net1, [(net1, "Powerrail"), (X0, "in"), (X1, "in")]);
            //WireConnector.Connect(net1, [(X0, "out"), (vn, "in1")]);
            //WireConnector.Connect(net1, [(X1, "out"), (vn, "in2")]);
            //WireConnector.Connect(net1, [(vn, "out"), (Y1, "in"), (Y2, "in"), (Y3, "in")]);

            //测试2
            WireConnector.Connect(net1, [(powerrail, "Powerrail"), (X0, "in")]);
            WireConnector.Connect(net1, [(X0, "out"), (Y1, "in"), (Y2, "in"), (Y3, "in")]);

            //WireConnector.Connect(net1, [(X0, "out"), (vn, "in1")]);

            //WireConnector.Connect(net1, [(Y0, "out"), (vn, "in2")]);

            //WireConnector.Connect(net1, [(vn, "out"), (Y1, "in1")]);

            //WireConnector.Connect(net1, [(vn, "out"), (Y0C, "in1")]);



        }

        public void testData()
        {
            #region test xml
            var dirpath = @"D:\work\2025-04-Tools\西门子xml\C#tt";
            //var dirpath = @"D:\work\2025-04-Tools\西门子xml\PVW2010_xmltestuse";
            //var dirpath = @"C:\Users\wstar\Desktop\work\2025.3\上位机学习demo\demo-stack\gptDataType\gptDataType\PLC 数据类型";
            List<Shinva.PLCModel.Helper.FileInfo> testFileInfos = ParseXmzXml.ParseXmlFiles(dirpath);
            int DB_index = 0;
            int FB_index = 0;
            int FC_index = 0;
            int OB_index = 0;
            foreach (var fileInfo in testFileInfos)
            {
                switch (fileInfo.FileType)
                {
                    case "InstanceDB":
                    case "GlobalDB":
                        { 
                        var db = new PlcDB(DB_index, fileInfo.FileName);
                        if (fileInfo.PlcStruct != null)
                        {
                            var members = fileInfo.PlcStruct.GetMembers();
                            if (members.Count > 0)
                            {
                                foreach (var Memberitem in members)
                                {
                                    if (Memberitem.DataType == DataType.Struct)
                                    {
                                        switch (Memberitem.Name)
                                        {
                                            case "Static":
                                                db.StaticStruct = (PlcStruct)Memberitem;
                                                break;
                                            default:
                                                break;
                                        }
                                    }
                                }
                            }
                        } 
                        plcModelService.DBList.Add(db);
                            db.InterfaceVariableTable.compileAddr();
                            DB_index++;
                        }
                        break;
                    case "FB":
                        {
                            // 初始化一个FB块
                            var fb = new PlcFB(Shinva.PLCModel.ProgrammingLanguage.LAD, FB_index, fileInfo.FileName);
                            if (fileInfo.PlcStruct != null)
                            {
                                var members = fileInfo.PlcStruct.GetMembers();
                                if (members.Count > 0)
                                {
                                    foreach (var Memberitem in members)
                                    {
                                        if (Memberitem.DataType == DataType.Struct)
                                        {
                                            switch (Memberitem.Name)
                                            {
                                                case "Input":
                                                    fb.InputStruct = (PlcStruct)Memberitem;
                                                    break;
                                                case "Output":
                                                    fb.OutputStruct = (PlcStruct)Memberitem;
                                                    break;
                                                case "InOut":
                                                    fb.InOutStruct = (PlcStruct)Memberitem;
                                                    break;
                                                case "Static":
                                                    fb.StaticStruct = (PlcStruct)Memberitem;
                                                    break;
                                                case "Temp":
                                                    fb.TempStruct = (PlcStruct)Memberitem;
                                                    break;
                                                case "Constant":
                                                    fb.ConstantStruct = (PlcStruct)Memberitem;
                                                    break;
                                                default:
                                                    break;
                                            }
                                        }
                                    }
                                }

                            }
                            plcModelService.FBList.Add(fb);
                            fb.InterfaceVariableTable.compileAddr();
                            FB_index++;
                        }

                        break;
                    case "FC":
                        {
                            var fc = new PlcFC(Shinva.PLCModel.ProgrammingLanguage.LAD, FB_index, fileInfo.FileName);
                            if (fileInfo.PlcStruct != null)
                            {
                                var members = fileInfo.PlcStruct.GetMembers();
                                if (members.Count > 0)
                                {
                                    foreach (var Memberitem in members)
                                    {
                                        if (Memberitem.DataType == DataType.Struct)
                                        {
                                            switch (Memberitem.Name)
                                            {
                                                case "Input":
                                                    fc.InputStruct = (PlcStruct)Memberitem;
                                                    break;
                                                case "Output":
                                                    fc.OutputStruct = (PlcStruct)Memberitem;
                                                    break;
                                                case "InOut":
                                                    fc.InOutStruct = (PlcStruct)Memberitem;
                                                    break;
                                                case "Temp":
                                                    fc.TempStruct = (PlcStruct)Memberitem;
                                                    break;
                                                case "Constant":
                                                    fc.ConstantStruct = (PlcStruct)Memberitem;
                                                    break;
                                                case "Return":
                                                    fc.ReturnStruct = (PlcStruct)Memberitem;
                                                    break;
                                                default:
                                                    break;
                                            }
                                        }
                                    }
                                }

                            }
                            plcModelService.FCList.Add(fc);
                            fc.InterfaceVariableTable.compileAddr();
                            FC_index++;
                        }
                        break;
                    case "OB":
                        {
                            var ob = new PlcOB(OB_index, fileInfo.FileName);
                            if (fileInfo.PlcStruct != null)
                            {
                                var members = fileInfo.PlcStruct.GetMembers();
                                if (members.Count > 0)
                                {
                                    foreach (var Memberitem in members)
                                    {
                                        if (Memberitem.DataType == DataType.Struct)
                                        {
                                            switch (Memberitem.Name)
                                            {
                                                case "Input":
                                                    ob.InputStruct = (PlcStruct)Memberitem;
                                                    break;
                                                case "Temp":
                                                    ob.TempStruct = (PlcStruct)Memberitem;
                                                    break;
                                                case "Constant":
                                                    ob.ConstantStruct = (PlcStruct)Memberitem;
                                                    break;
                                                default:
                                                    break;
                                            }
                                        }
                                    }
                                }

                            }
                            ob.InterfaceVariableTable.compileAddr();
                            plcModelService.OBList.Add(ob);
                            OB_index++;
                        }
                        break;
                    case "PlcStruct":
                        {
                            var pv = new PlcVariable(fileInfo.FileName);
                            if (fileInfo.PlcStruct != null)
                            {
                                var members = fileInfo.PlcStruct.GetMembers();
                                if (members.Count > 0)
                                {
                                    foreach (var Memberitem in members)
                                    {
                                        if (Memberitem.DataType == DataType.Struct)
                                        {
                                            switch (Memberitem.Name)
                                            {
                                                case "None":
                                                    pv.NoneStruct = (PlcStruct)Memberitem;
                                                    break;
                                                default:
                                                    break;
                                            }
                                        }
                                    }
                                }

                            }
                            pv.InterfaceVariableTable.compileAddr();
                            plcModelService.PlcVariable.Add(pv);
                        }
                        break;
                    default:
                        Debug.WriteLine($"未知文件类型{fileInfo.FileType}");
                        break;
                }
                
            }
            #endregion
            fil = testFileInfos[1].diagram;
        }
    }
}
